﻿//Created by Action Script Viewer - http://www.buraks.com/asv
package Transactions.tracking {
    import Engine.Transactions.*;
    import Engine.Managers.*;
    import flash.utils.*;
    import Transactions.*;
    import __AS3__.vec.*;
    import Modules.stats.experiments.*;

    public class DesyncTracker {

        private static const MAX_COMPLETED_TRANSACTIONS:int = 20;
        private static const MAX_RECENT_TRANSACTIONS:int = 10;

        private var m_pendingTransactions:Dictionary;
        private var m_completedTransactions:Vector.<TransactionData>;
        private var m_transactionCount:int = 0;
        private var m_recentTransactions:Vector.<String>;
        private var m_transactionServiceMap:Dictionary;

        public function DesyncTracker(){
            this.m_pendingTransactions = new Dictionary();
            this.m_completedTransactions = new Vector.<TransactionData>();
            this.m_recentTransactions = new Vector.<String>();
            this.m_transactionServiceMap = new Dictionary();
            super();
        }
        public function onAdd(_arg1:Transaction):void{
            if (!this.isEnabled()){
                return;
            };
            while (this.m_recentTransactions.length >= MAX_RECENT_TRANSACTIONS) {
                this.m_recentTransactions.shift();
            };
            this.m_recentTransactions.push(this.generateTransactionKey(_arg1));
            var _local2:TransactionData = new TransactionData();
            _local2.transaction = _arg1;
            _local2.initialClientState = ResourceState.getClientState();
            _local2.recentTransactions = this.m_recentTransactions.slice();
            this.m_pendingTransactions[_arg1.getId()] = _local2;
        }
        public function onComplete(_arg1:Transaction):void{
            var _local3:String;
            var _local4:String;
            if (!this.isEnabled()){
                return;
            };
            var _local2:TransactionData = this.m_pendingTransactions[_arg1.getId()];
            if (_local2 != null){
                this.m_transactionCount++;
                _local3 = this.generateTransactionKey(_arg1);
                _local4 = _arg1.rawResult["service"];
                if (this.m_transactionServiceMap[_local3] !== undefined){
                    if (this.m_transactionServiceMap[_local3] !== _local4){
                        throw (new Error("Transaction -> Service mapping collision"));
                    };
                } else {
                    this.m_transactionServiceMap[_local3] = _local4;
                };
                _local2.finalClientState = ResourceState.getClientState();
                _local2.initialServerState = ResourceState.getInitialServerState(_arg1);
                _local2.finalServerState = ResourceState.getFinalServerState(_arg1);
                while (this.m_completedTransactions.length >= MAX_COMPLETED_TRANSACTIONS) {
                    this.m_completedTransactions.shift();
                };
                this.m_completedTransactions.push(_local2);
                delete this.m_pendingTransactions[_arg1.getId()];
                this.checkForDesync(_arg1);
            };
        }
        public function onFault(_arg1:Transaction):void{
            if (!this.isEnabled()){
                return;
            };
            var _local2:TransactionData = this.m_pendingTransactions[_arg1.getId()];
            if (_local2 != null){
                delete this.m_pendingTransactions[_arg1.getId()];
            };
        }
        private function checkForDesync(_arg1:Transaction):void{
            var _local7:String;
            var _local8:String;
            var _local2:TransactionData = this.m_completedTransactions[(this.m_completedTransactions.length - 1)];
            var _local3:int = _arg1.rawResult["actionCount"];
            if (this.m_transactionCount != _local3){
                this.logDesync(_arg1);
                return;
            };
            var _local4:Array = _arg1.rawResult["recentActions"];
            var _local5:int = (_local4.length - 1);
            var _local6:int = (_local2.recentTransactions.length - 1);
            while ((((_local5 >= 0)) && ((_local6 >= 0)))) {
                _local7 = _local4[_local5];
                _local8 = this.m_transactionServiceMap[_local2.recentTransactions[_local6]];
                if (_local7 != _local8){
                    this.logDesync(_arg1);
                    return;
                };
                _local5--;
                _local6--;
            };
        }
        private function logDesync(_arg1:Transaction):void{
            var _local3:String;
            var _local4:String;
            var _local2:TransactionData = this.m_completedTransactions[(this.m_completedTransactions.length - 1)];
            StatsManager.count("server_tranasction_oos", _arg1.rawResult["actionCount"]);
            for each (_local3 in _arg1.rawResult["recentActions"]) {
                StatsManager.count("server_tranasction_oos", _local3);
            };
            StatsManager.count("client_tranasction_oos", this.m_transactionCount.toString());
            for each (_local4 in _local2.recentTransactions) {
                StatsManager.count("client_tranasction_oos", this.m_transactionServiceMap[_local4]);
            };
        }
        private function generateTransactionKey(_arg1:Transaction):String{
            var _local3:TWorldState;
            var _local2:String = getQualifiedClassName(_arg1);
            if ((_arg1 is TWorldState)){
                _local3 = (_arg1 as TWorldState);
                _local2 = (_local2 + (("(" + getQualifiedClassName(_local3.getWorldObject())) + ")"));
            };
            return (_local2);
        }
        private function isEnabled():Boolean{
            var _local1:int = Global.experimentManager.getVariant(ExperimentDefinitions.EXPERIMENT_DOOBER_TRACKING);
            return ((_local1) ? true : false);
        }

    }
}//package Transactions.tracking 

import Engine.Transactions.*;
import __AS3__.vec.*;

class TransactionData {

    public var transaction:Transaction;
    public var recentTransactions:Vector.<String>;
    public var initialClientState:ResourceState;
    public var finalClientState:ResourceState;
    public var initialServerState:ResourceState;
    public var finalServerState:ResourceState;

    public function TransactionData(){
    }
}
